package graphics.Shapes;

import java.nio.ByteBuffer;

import javax.media.opengl.GL;

import com.sun.opengl.util.BufferUtil;
import common.Point3D;

import game.TracingCamera;
import graphics.GraphicalObject;

public class TexturedQuad extends GraphicalObject {

	int texture;
	public int width=64;
	public int height=64;
	boolean isInitialized = false;
	boolean hasFrame = false;
	
	int glListDescriptor = -1;
	GL glListHolder = null;

	
	public Point3D p0,p1,p2,p3;
	
	public TexturedQuad(){
		p0 = new  Point3D(0,0,0);
		p1 = new  Point3D(0,0,0);
		p2 = new  Point3D(0,0,0);
		p3 = new  Point3D(0,0,0);
	}
	
	public void updateViewPort(GL gl){
		gl.glViewport(0, 0, width, height);
	}
	
	public void bindTexture(GL gl){
		if (!isInitialized){
			initialize(gl);
		}
		gl.glBindTexture(GL.GL_TEXTURE_2D, 0);					// Bind To The Blur Texture
		gl.glEnable(GL.GL_TEXTURE_2D);									// Disable 2D Texture Mapping
		gl.glBindTexture(GL.GL_TEXTURE_2D, texture);					// Bind To The Blur Texture
		gl.glCopyTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, 0, 0, width, height, 0);
	}
	
	
	@Override
	public void initialize(GL gl) {
		super.initialize(gl);
		texture = createEmptyTexture(gl, width, height);
	
		glListDescriptor = gl.glGenLists(1);
		glListHolder = gl;

		gl.glNewList(glListDescriptor, GL.GL_COMPILE);
		renderQuad(gl);
		
		gl.glEndList();

	}

	//@Override
	public void render(GL gl) {
		
		gl.glCallList(glListDescriptor);
	}

	private void renderQuad(GL gl) {
		gl.glBindTexture(GL.GL_TEXTURE_2D, texture);					// Bind To The Blur Texture

		gl.glPushAttrib(GL.GL_ENABLE_BIT);
		gl.glEnable(GL.GL_TEXTURE_2D);									// Disable 2D Texture Mapping
		gl.glDisable(GL.GL_COLOR_MATERIAL);		    

		gl.glColor3f(0.5f, 0.5f, 0.5f);
		gl.glLineWidth(1);

		gl.glBegin(GL.GL_QUADS);
		gl.glTexCoord2d(0,0);
		gl.glVertex3d(-1, -1,0);
		gl.glTexCoord2d(0,1);
		gl.glVertex3d(-1, 1,0);
		gl.glTexCoord2d(1,1);
		gl.glVertex3d(1, 1,0);
		gl.glTexCoord2d(1,0);
		gl.glVertex3d(1, -1,0);
		gl.glEnd();

		gl.glDisable(GL.GL_TEXTURE_2D);
		
		gl.glBegin(GL.GL_LINE_LOOP);
		gl.glVertex3d(-1, -1,0);
		gl.glVertex3d(-1, 1,0);
		gl.glVertex3d(1, 1,0);
		gl.glVertex3d(1, -1,0);
		gl.glEnd();

		gl.glPopAttrib();
		// Disable 2D Texture Mapping
		gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
	}

	public int getTexture() {
		return texture;
	}

	public void setTexture(int texture) {
		this.texture = texture;
	}
	
	
	private int createEmptyTexture(GL gl, int width, int height) {											// Create An Empty Texture
		ByteBuffer data = BufferUtil.newByteBuffer(width * height * 4); // Create Storage Space For Texture Data (128x128x4)
		data.limit(data.capacity());

		int[] txtnumber = new int[1];
		gl.glGenTextures(1, txtnumber, 0);								// Create 1 Texture
		gl.glBindTexture(GL.GL_TEXTURE_2D, txtnumber[0]);					// Bind The Texture
		gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, 4, width, height, 0,
				GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, data);						// Build Texture Using Information In data
		gl.glTexParameterf(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_WRAP_S,GL.GL_CLAMP);	 	
		gl.glTexParameterf(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_WRAP_T,GL.GL_CLAMP);	
		gl.glTexParameterf(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MAG_FILTER,GL.GL_LINEAR); 
		gl.glTexParameterf(GL.GL_TEXTURE_2D,GL.GL_TEXTURE_MIN_FILTER,GL.GL_LINEAR);
		//gl.glTexEnvf(GL.GL_TEXTURE_ENV,GL.GL_TEXTURE_ENV_MODE,GL.GL_DECAL); 

		return txtnumber[0];											// Return The Texture ID
	}
	
	
	private void viewOrtho(GL gl)												// Set Up An Ortho View
	{
		gl.glMatrixMode(GL.GL_PROJECTION);								// Select Projection
		gl.glPushMatrix();												// Push The Matrix
		gl.glLoadIdentity();											// Reset The Matrix
		gl.glOrtho(0, 640, 480, 0, -1, 1);							// Select Ortho Mode (640x480)
		gl.glMatrixMode(GL.GL_MODELVIEW);									// Select Modelview Matrix
		gl.glPushMatrix();												// Push The Matrix
		gl.glLoadIdentity();											// Reset The Matrix
	}

	private void viewPerspective(GL gl)											// Set Up A Perspective View
	{
		gl.glMatrixMode(GL.GL_PROJECTION);								// Select Projection
		gl.glPopMatrix();												// Pop The Matrix
		gl.glMatrixMode(GL.GL_MODELVIEW);								// Select Modelview
		gl.glPopMatrix();												// Pop The Matrix
	}

	public void renderOrthogonal(GL gl) {
		
		gl.glPushAttrib(GL.GL_ENABLE_BIT);
		gl.glEnable(GL.GL_TEXTURE_2D);									// Disable 2D Texture Mapping
		gl.glBindTexture(GL.GL_TEXTURE_2D, texture);					// Bind To The Blur Texture

		gl.glDisable(GL.GL_LIGHTING);
		gl.glDisable(GL.GL_BLEND);
		gl.glDisable(GL.GL_COLOR_MATERIAL);		    

		viewOrtho(gl);
		gl.glBegin(GL.GL_QUADS);
		gl.glColor3f(0.5f, 0.5f, 0.5f);
		
		gl.glTexCoord2d(0,0);
		gl.glVertex2d(0,0);

		gl.glTexCoord2d(0,1);
		gl.glVertex2d(0,400);

		gl.glTexCoord2d(1,1);
		gl.glVertex2d(400,400);

		gl.glTexCoord2d(1,0);
		gl.glVertex2d(400,0);
		
		gl.glEnd();
		

		gl.glEnable(GL.GL_LIGHTING);
		gl.glDisable(GL.GL_TEXTURE_2D);
		gl.glPopAttrib();
		// Disable 2D Texture Mapping

	}

	
	@Override
	protected void finalize() throws Throwable {
		glListHolder.glDeleteLists(glListDescriptor, 1);
		super.finalize();
	}
	
}
